<template>
  <div class="formBody">
    <el-card>
      <el-form ref="formRef" :model="modelValue" :rules="rules" label-width="auto">
        <el-row :gutter="20">
          <el-col
            v-for="item in formItemsNew"
            :key="item.field"
            :span="item.cloumn || 24"
          >
            <el-form-item
              :label="item.label"
              :prop="item.field"
              :rules="{ required: item.required, message: `${item.label}不能为空` }"
            >
              <slot :name="item.field">
                <component
                  v-model="modelValue[item.field]"
                  :is="getComponent(item)"
                  v-bind="getComponentProps(item)"
                  @change="handleSelectV2QueryChange(item)"
                >
                  <!-- 动态渲染组件内部插槽 -->
                  <template v-for="(slotConfig, slotName) in item.slots" #[slotName]>
                    <component
                      :key="slotName"
                      :is="slotConfig.component || 'div'"
                      v-bind="slotConfig.props || {}"
                      v-on="slotConfig.events || {}"
                    >
                      {{ slotConfig.content }}
                    </component>
                  </template>

                  <!-- 当组件是select时，添加options -->
                  <template v-if="item.formType === 'select'">
                    <el-option
                      v-for="opt in item.props.options"
                      :key="opt.value"
                      :label="opt.label"
                      :value="opt.value"
                    />
                  </template>
                  <!-- 当组件是radio时，添加options -->
                  <template v-if="item.formType === 'radio'">
                    <el-radio
                      v-for="opt in item.props.options"
                      :key="opt.value"
                      :label="opt.label"
                      :value="opt.value"
                    />
                  </template>
                  <!-- 当组件是radio时，添加options -->
                  <template v-if="item.formType === 'checkBox'">
                    <el-checkbox
                      v-for="opt in item.props.options"
                      :key="opt.value"
                      :label="opt.label"
                      :value="opt.value"
                    />
                  </template>
                </component>
              </slot>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
  </div>
</template>
<script setup >
import {
  ElInput,
  ElInputNumber,
  ElSelect,
  ElDatePicker,
  ElRadioGroup,
  ElRate,
  ElSelectV2,
  ElCheckboxGroup,
  ElColorPicker,
  ElCascader,
  ElSwitch,
  ElTree
} from "element-plus";
import { useTemplateRef, computed } from "vue";
const props = defineProps({
  formItems: {
    type: Array,
    required: true,
  },
  rules: {
    type: Object,
    default: () => ({}),
  },
});
const slots = defineSlots();
console.log("slots", slots);
//defineModel相当于： defineProps(['modelValue']) defineEmits(['update:modelValue'])
const modelValue = defineModel(); //默认值是modelValue
// 组件映射
const componentMap = {
  input: ElInput,
  number: ElInputNumber,
  select: ElSelect,
  date: ElDatePicker,
  radio: ElRadioGroup,
  rate: ElRate,
  selectV2: ElSelectV2,
  checkBox: ElCheckboxGroup,
  colorPicker: ElColorPicker,
  cascader: ElCascader,
  switch : ElSwitch,
  tree : ElTree,
};
// 获取组件：可能存在自定义组件
function getComponent(item) {
  const { formType } = item;
  if (formType && typeof formType !== "string") {
    return formType;
  }
  return componentMap[item.formType || "input"];
}
// 获取组件属性
function getComponentProps(item) {
  const { props } = item;
  if (item.formType === "date") {
    // 日期类型：数据格式化
    let type = props?.type;
    let valueFormat = type === "datetime" ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
    let format = type === "datetime" ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
    return Object.assign({ valueFormat, format }, props);
  }
  return props || {};
}
// 虚拟化选择器（selectV2）的queryChange事件，绑定远程方法，在标签中直接使用? eslint会报错
function handleSelectV2QueryChange(item) {
  if (item.formType === "selectV2" && item.props?.remoteMethod) {
    item.props.remoteMethod();
  }
}

// 过滤隐藏字段
const formItemsNew = computed(() => {
  return props.formItems.filter((item) => !item.hidden);
});

const formRootPops = ["label", "field", "formType"];
// 过滤出配置项（废弃）
function gettemplateProps(item) {
  if (item.props) return item.props;
  return formRootPops.reduce((obj, key) => {
    obj[key] = item[key];
    return obj;
  }, {});
}

//获取表单实例，使用ref需要声明的变量与模板中的ref属性名一致
// const formRef = ref(null);
//使用useTemplateRef可以直接获取模板中的ref属性名
const formRef2 = useTemplateRef("formRef");
//表单校验
async function formValidate() {
  try {
    await formRef2.value.validate();
    return true;
  } catch (error) {
    return false;
  }
}

defineExpose({
  formValidate,
});
</script>
<style lang="scss" scoped>
.formBody {
  background: #fff;
}
</style>
